use crate::{backup::{BackupError, BackupEvaluation}, common::{Chunk, Evaluated}, container::ContainerId, index::FingerPrintStoreSelector, pipeline::MutExecutor};

use super::{BackupResult, SeqChunk, SourcePool, WriteItem};

pub struct ChunkWriter {
    tmp_id:ContainerId,
    write_time:u128,
    fp_store:FingerPrintStoreSelector,
}

impl ChunkWriter {
    pub fn from_source(source:&SourcePool) -> Self {
        let fp_store = source.fp_store.clone();
        Self { 
            tmp_id:0,
            write_time:0,
            fp_store, 
        }
    }

    pub fn write_chunk(&mut self, chunk:SeqChunk) -> BackupResult<()> {
        let id = chunk.file_id;
        let chunk = chunk.chunk;
        self.fp_store.insert_fp_with_container_id(chunk.fp(), id as ContainerId)?;
        Ok(())
    }

    pub fn write(&mut self, write_item:WriteItem) -> BackupResult<()> {
        match write_item {
            WriteItem::File(_) => {},
            WriteItem::Chunk(chunk) => self.write_chunk(chunk)?,
            WriteItem::ChunkPointer(_) => {},
        }
        Ok(())
    }
}

impl Evaluated for ChunkWriter {
    fn register(&self, evaluation:&crate::common::Evaluation) {
        let mut eva = evaluation.lock();
        eva.register(BackupEvaluation::Time, "write time(us)");
    }

    fn set_value(&self, evaluation:&crate::common::Evaluation) {
        let mut eva = evaluation.lock();
        eva.set("write time(us)", self.write_time);
    }
}

impl MutExecutor<WriteItem, ()> for ChunkWriter {
    type Error = BackupError;
    fn exec<'scope, F:FnMut(())>(&'scope mut self, input:WriteItem, _output:F) -> Result<(), Self::Error> {
        self.write(input)
    }
}